/**
 * 
 */
package ua.kpi.javatrainee6.model.people;

import ua.kpi.javatrainee6.model.assessment.*;
import ua.kpi.javatrainee6.model.curriculum.*;
import ua.kpi.javatrainee6.model.departments.*;

/**
 * Student entity, contains group and lists of marks
 * Provides next functionality: you can view your marks, curriculum,
 * abilities and average score and calculate your scholarship, view your evaluation
 */
public final class Student extends Person implements CurriculumPrintable, Evaluable, Observer {
	
	private static final double SCORE_FOR_BASIC_SALARY = 4.0;
	private static final double SCORE_FOR_GREAT_SALARY = 5.0;
	private static final double BASIC_SALARY = 750.0;
	private static final double GREAT_SALARY = 800.0;
	private GroupInfo group;
	private Marks marks;
    private Observable observerPerson; 
    
	/**
	 * Optional constructor, used now for automatic data generation, for more detailed description
	 * look in Person class
	 * @param group - reference for curriculum view
	 */
	public Student(GroupInfo group, Observable observerPerson) {
		super();
		this.group = group;
		this.observerPerson = observerPerson;
	}
	
	/**
	 * Assessment setting, is used by University Administrator
	 */
	public void setMarks(Marks marks) {
		this.marks = marks;
	}
	
	public GroupInfo getGroup() {
		return group;
	}
	
	/**
	 * Specific for student (for his/her group) curriculum, implementation of CurriculumPrintable 
	 * method 
	 */
	public void viewCurriculum() {
		Curriculum curriculum = group.getUniver().getCurriculum();
		System.out.printf("Curriculum for student %s of group %s\n", getShortDescription(),
				           group.getTitle());
		curriculum.printCurriculum(this);
	}
	
	/**
	 * Viewing responsibilities, implementation of abstract method of Person class
	 */
    public void viewResponsibilities() {
    	System.out.println("YOUR RESPONSIBILITIES");
		System.out.println("As student you can:\nYou can only view curriculum and general " +
				           "information about university\n + your average score");
	}
    
    /**
     * Looking through student marks, information about subject and teacher is produced
     * If Administrator has not performed assessment yet, marks can be uninitialized
     */
    public void viewAllMarks() {
    	System.out.println("All marks for student " + getShortDescription());
    	if (marks == null) {
    		System.out.println("Adminstrator did not performed assessment, no marks.");
    		return;
    	}
    	for (Assessment mark : marks) {
    		System.out.println(mark);
    	}
    }
    
    public boolean isAssessmentDone() {
    	UniversityAdministrator admin = group.getUniver().getAdmin();
    	return admin.isAssessmentDone();
    }
    /**
     * Calculating average mark for student
     * If Administrator has not performed assessment yet, marks can be uninitialized
     */
    public double calculateAverage() {
    	if (!isAssessmentDone()) {
    		return 0.0;
    	}
    	int sum = 0;
    	for(Assessment mark : marks) {
    		sum += mark.getMark().getMarkItem();
    	}
    	return (double) sum / marks.count();
    }
    
    /**
     * Calculating student salary - scholarship, it depends on average mark
     */
    public double calculateSalary() {
    	double averageMark = calculateAverage();
    	if (averageMark >= SCORE_FOR_GREAT_SALARY) {
    		return GREAT_SALARY;
    	} else if (averageMark >= SCORE_FOR_BASIC_SALARY) {
    		return BASIC_SALARY;
    	} else {
    		return 0.0;
    	}
    }
    
    /**
     * Evaluation for student, implementation from Evaluable interface
	 * depends on student average mark
     */
    public void evaluateAsBadOrGood() {
    	System.out.printf("Results of evaluation for student %s:\n", getShortDescription());
		double compareScore = calculateAverage();
		if (compareScore >= GOOD_SCORE) {
			System.out.println("Thank you, you are very good student");
		} else if (compareScore >= BAD_SCORE) {
			System.out.println("Thank you, you are good student");
		} else {
			System.out.println("Unfortunately, you are bad student");
		}
	}
    
    @Override
	public String toString() {
		return String.format("Information about student:\nPersonal info:\n%s\nGroup: %s\n",
				              super.toString(), group);		        
	}
    
    @Override 
	public boolean equals(Object otherObject) {
		if (! super.equals(otherObject)) {
			return false;
		}
		Student other = (Student) otherObject;
		if (group.equals(other.group)) {
			return true;
		} else {
			return false;
		}
	}
    
    public Marks getMarks() {
    	return marks;
    }

	public void becomeObserver() {
		observerPerson.registerObserver(this);	
	}

	public void stopToBeObserver() {
		observerPerson.removeObserver(this);
	}

	public void update() {
		System.out.printf("I am student %s.\nSome info about assessments to me, I can view my marks\n", 
				          getShortDescription());
	}  
}